package com.etop.controller;

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.List;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;

import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.etop.basic.controller.BaseController;
import com.etop.pojo.User;
import com.etop.service.UserService;
import com.etop.utils.VerifyCode;

@Controller
public class HomeController extends BaseController {
   private final static Logger log=Logger.getLogger(HomeController.class);
   @Resource
   private UserService userService;
   /*
    * @RequestMapping:总共有6个属性
    * @value：指定请求的实际地址，指定的地址可以是URI Template 模式（后面将会说明）；
    * @method：  指定请求的method类型， GET、POST、PUT、DELETE等；
    * @produces:指定返回的内容类型，仅当request请求头中的（Accept）类型中包含该指定类型才返回
    * @consumens:指定处理请求的提交内容类型（Content-Type）,例如：application/json,text/html;
    * @params:指定request中必须包含某些参数是，才让该方法处理
    * @headers:直定request中必须包含某些指定的header值，才让该方法处理请求
    */ 
   @RequestMapping(value="/login.html",method=RequestMethod.GET,produces="text/html;charset=utf-8")
   public String loginForm(Model model,String message){
	   if(!StringUtils.isEmpty(message))
		   model.addAttribute(message);
	   model.addAttribute("user", new User());
	   System.out.println("login_1");
	   System.out.println("model:"+model);
	   System.out.println("message:"+message);
	   log.info("login.html");
	   return "login";
	   
   }
   
   @RequestMapping("/verifyCode.html")
   public void verifyCode(HttpServletRequest request,HttpServletResponse response) throws IOException{
       log.info("verify.html");
	   response.setHeader("Pragma", "no-cache");
	   response.setHeader("Cache-Control", "no-cache");
	   response.setDateHeader("Expires", 0);
	   //生成验证码，写入用户session
	   String verifyCode=VerifyCode.generateTextCode(VerifyCode.TYPE_ALL_MIXED, 4, null);
	   request.getSession().setAttribute(VerifyCode.VERIFY_TYPE_COMMENT, verifyCode);
	   System.out.println("verifyCode:"+verifyCode);
	   //输出验证码给客户端
	   response.setContentType("image/jpeg");
	   BufferedImage bi=VerifyCode.generateImageCode(verifyCode, 65, 22, 8, true, Color.WHITE, Color.BLACK, null);
	   ServletOutputStream out=response.getOutputStream();
	   ImageIO.write(bi, "JPEG", out);
	   log.info("验证码已经生成并存入session中");
	   try{
	   out.flush();
	   log.info("刷新验证码图片");
	   }finally {
		   out.close();
		   log.info("关闭验证码流");
	   }
	   
   }
   
   //登录用户名、密码、验证码验证
   /**
    * @author Administrator
    * @param user 对对象user进行验证（@Valid）
    * @param model 添加返回参数
    * @param attr 给重定向请求传入参数
    * @param bindingResult 
    *   login方法接收的参数user是用@Valid进行标注的，这里的@Valid是定义在JSR-303标准中的，
    *   我这里使用的是Hibernate Validation对它的实现。这里我们必须使用@Valid标注我们需要校验的参数user，
    *   否则Spring不会对它进行校验。另外我们的处理器方法必须给定包含Errors的参数，这可以是Errors本身，也可以是它的子类BindingResult，
    *   使用了Errors参数就是告诉Spring关于表单对象数据校验的错误将由我们自己来处理，否则Spring会直接抛出异常，而且这个参数是必须紧挨着@Valid参数的，
    *   即必须紧挨着需要校验的参数，这就意味着我们有多少个@Valid参数就需要有多少个对应的Errors参数，它们是一一对应的。
    * @param request servlet容器请求对象
    * 
    */
   @RequestMapping(value="/login.html",method=RequestMethod.POST,produces="text/html;charset=utf-8")
   public String login(@Valid User user,BindingResult bindingResult,
		               Model model,RedirectAttributes attr,HttpServletRequest request){
	   HttpSession session=request.getSession();
	   //session为空时挑战时，跳转到登录页面
	   if(session.getAttribute(VerifyCode.VERIFY_TYPE_COMMENT)==null||
			   session.getAttribute(VerifyCode.VERIFY_TYPE_COMMENT)==""){
		   addMessage(attr,"session为空");
		   log.info("验证码为空");
		   return "redirect:/";
	   }
	   
	   String code=(String)session.getAttribute(VerifyCode.VERIFY_TYPE_COMMENT);
	   String submitCode=WebUtils.getCleanParam(request, "checkcode");
	   if(StringUtils.isEmpty(code)||StringUtils.isEmpty(submitCode)
			   ||StringUtils.equals(code, submitCode)){
		   addMessage(attr,"验证码错误");
		   log.info("验证码错误");
		   return "redirect:/";
	   }
	   boolean bl=bindingResult.hasErrors();
	   System.out.println(bl);
//	   Subject currentUser =SecurityUtils.getSubject();
//	   UsernamePasswordToken token=new UsernamePasswordToken(user.getUsername(),user.getPassword());
//	   User user1=userService.findByName(token.getUsername());
//	   System.out.println(user1.getUsername());
//	   return null;
	   try {
	   if(bl||user.getUsername().isEmpty()||user.getPassword().isEmpty()){
		   addMessage(attr,"用户名或密码错误");
		   log.info("用户名或密码错误");
		   return "redirect:/";
	   }
	   //管理用户登录
	   System.out.println("管理用户登录123");
	   //使用shiro管理用户登录
	   System.out.println("使用shiro登录验证");
	   Subject currentUser =SecurityUtils.getSubject();
	   UsernamePasswordToken token=new UsernamePasswordToken(user.getUsername(),user.getPassword());
	   currentUser.login(token);
	   //获取所有用户信息，权限由前端shiro标签控制
	   List<User> userList=userService.getAllUsers();
	   System.out.println(userList);
	   model.addAttribute("userList",userList);
	   System.out.println("管理用户登录成功");
	   log.info("成功登陆");
	   System.out.println("密码:"+user.getPassword());
	   return "user";
	   }catch(AuthenticationException e){
		   addMessage(attr,"用户名或密码错误");
		   System.out.println("用户名或密码错误");
		   log.info("用户名或密码错误");
		   return "redirect:/";
	   }
	   
   }
   
   //用户登出管理
   @RequestMapping(value="logout.html",method=RequestMethod.GET)
   public String logout(RedirectAttributes attr){
	   SecurityUtils.getSubject().logout();
	   addMessage(attr,"您已安全退出");
	   System.out.println("您已安全退出");
	   log.info("安全退出");
	   return "redirect:/";
   }
   
   //没有角色controller
   @RequestMapping("/403.html")
   public String unauthorizedRole(){
	   log.info("跳转到403页面");
	   return "403";
   }
}
